package com.example.mediarecorderdemo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.VideoCapture;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;

import android.util.Log;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.example.mediarecorderdemo.databinding.FragmentCameraXBinding;
import com.google.common.util.concurrent.ListenableFuture;

import java.io.File;
import java.util.concurrent.ExecutionException;

public class CameraXFragment extends Fragment {

    private FragmentCameraXBinding mCameraXBinding;
    private PreviewView mPreviewView;
    private VideoCapture mVideoCapture;
    private ProcessCameraProvider mProcessCameraProvider;
    private Preview mPreview;
    private boolean mIsRecording;
    private ListenableFuture<ProcessCameraProvider> mProviderListenableFuture;
    private ImageCapture mImageCapture;
    private Camera mCamera;

    public CameraXFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        mCameraXBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_camera_x, container, false);
        mCameraXBinding.setLifecycleOwner(requireActivity());
        return mCameraXBinding.getRoot();
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mCameraXBinding.btnTakePhoto.setOnClickListener(view -> {
            takePhoto();
        });
        mCameraXBinding.btnTakeVideo.setOnClickListener(view -> {
            if (!mIsRecording) {
                mCameraXBinding.btnTakeVideo.setText("停止录像");
                mIsRecording = true;
                takeRecorder();
            } else {
                mCameraXBinding.btnTakeVideo.setText("开始录像");
                stopRecorder();
                mIsRecording = false;
            }
        });
        mCameraXBinding.btnJump.setOnClickListener(view -> {
            NavController controller = Navigation.findNavController(view);
            controller.navigate(R.id.action_cameraXFragment_to_recordFragment);
        });
        startPreview();
    }

    @SuppressLint("RestrictedApi")
    private void startPreview() {
        //可以绑定生命周期的ProcessCameraProvider，ProcessCameraProvider
        // 它会和宿主绑定生命周期，这样就不用担心打开相机和关闭的问题
        mProviderListenableFuture
                = ProcessCameraProvider.getInstance(requireContext());
        //注册监听，第一个参数是一个 runnable，第二个参数是线程池
        mProviderListenableFuture.addListener(() -> {
            try {
                // //将相机的生命周期和activity的生命周期绑定，camerax会自己释放，不用担心了
                mProcessCameraProvider = mProviderListenableFuture.get();
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            }
            //创建preview，支持角度换算
            mPreview = new Preview.Builder().build();
            //将Preview连接到 PreviewView,进行预览
            mPreview.setSurfaceProvider(mCameraXBinding.previewView.getSurfaceProvider());
            //创建图片的capture
            mImageCapture = new ImageCapture.Builder()
                    .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                    .setTargetResolution(new Size(1920, 1080))
                    .build();
            //创建录像的capture
            mVideoCapture = new VideoCapture.Builder()
                    .setTargetRotation(mCameraXBinding.previewView.getDisplay().getRotation())
                    .setVideoFrameRate(30)
                    .setBitRate(5 * 1024 * 1024)
                    .build();

            ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
            imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(requireContext()),
                    image -> image.close());
            //解绑
            mProcessCameraProvider.unbindAll();
            //将数据绑定到相机的生命周期中
            mCamera = mProcessCameraProvider.bindToLifecycle(requireActivity(),
                    CameraSelector.DEFAULT_BACK_CAMERA //选择后置摄像头
                    , mVideoCapture, mPreview);
            //点击聚焦
            mCameraXBinding.previewView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    float x = motionEvent.getX();
                    float y = motionEvent.getY();
                    FocusMeteringAction focusMeteringAction = new FocusMeteringAction.Builder(
                            mCameraXBinding.previewView.getMeteringPointFactory()
                                    .createPoint(x, y)).build();
                    mCamera.getCameraControl().startFocusAndMetering(focusMeteringAction);
                    return true;
                }
            });
        }, ContextCompat.getMainExecutor(requireContext()));
    }

    @SuppressLint("RestrictedApi")
    private void stopRecorder() {
        if (mVideoCapture != null){
            //停止录像
            mVideoCapture.stopRecording();
        }
    }

    @SuppressLint("RestrictedApi")
    private void takeRecorder() {
        File file = new File(requireActivity().getExternalFilesDir("").getAbsoluteFile(), "camerax.mp4");
        if (file.exists()) {
            file.delete();
        }
        //创建视频文件的数据，比如创建文件
        VideoCapture.OutputFileOptions fileOptions = new VideoCapture.OutputFileOptions
                .Builder(file).build();
        if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        //开始拍照，拍照之前需要进行权限确认
        mVideoCapture.startRecording(fileOptions, ContextCompat.getMainExecutor(requireActivity())
                , new VideoCapture.OnVideoSavedCallback() {
                    //保存录像
                    @Override
                    public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) {
                        Toast.makeText(requireActivity(), "视频已保存"
                                + outputFileResults.getSavedUri().getPath(), Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
                        Log.e("TAG", "onError: ");
                        //视频不足一秒会走到这里来，但是视频依然生成了，所以得删掉
                        file.delete();
                    }
                });
    }

    private void takePhoto() {
        File file = new File(requireActivity().getExternalFilesDir("").getAbsoluteFile(), "camerax.jpg");
        if (file.exists()) {
            file.delete();
        }
        //创建图片文件的数据
        ImageCapture.OutputFileOptions outputFileOptions =
                new ImageCapture.OutputFileOptions.Builder(file).build();
        mProcessCameraProvider.bindToLifecycle(requireActivity(), CameraSelector.DEFAULT_BACK_CAMERA
                , mImageCapture);
        //开始拍照
        mImageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(requireActivity()),
                new ImageCapture.OnImageSavedCallback() {
                    @Override
                    public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                        Uri savedUri = outputFileResults.getSavedUri();
                        if (savedUri == null) {
                            savedUri = Uri.fromFile(file);
                        }
                        Toast.makeText(requireActivity(), "拍摄成功,路径为" + savedUri
                                , Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(@NonNull ImageCaptureException exception) {
                        Log.e("TAG", "onError: ");
                    }
                });
    }

}